/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Quaternions.
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define MATH_QUATERNION_CC 1
#include "base/module.hh"
#include "base/stream.hh"
using namespace base;
#include "math/module.hh"
#include "math/quaternion.hh"
#include "math/matrix.hh"
#include "math/funcs_vector.hh"

namespace math {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////  QuaternionPosition  /////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * ctor.
 *****************************************************************************/
QuaternionPosition::QuaternionPosition( void )
:   mQuat(),
    mPos(0,0,0)
{
    // NOP
}

QuaternionPosition::QuaternionPosition( const Quaternion& quat, const Vector3& pos )
:   mQuat(quat),
    mPos(pos)
{
    // NOP
}

// This is a way to shrink a Matrix (while keeping its position).
QuaternionPosition::QuaternionPosition( const Matrix& matrix )
:   mQuat(matrix),
    mPos(matrix.GetPosition())
{
    // NOP
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////  functions  /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * Interpolate between two quaternions.
 * fraction = 0 : return m0
 * fraction = 1 : return m1
 *****************************************************************************/
Quaternion
Interpolate( const Quaternion& q0, const Quaternion& q1, const fp fraction )
{
MATH_EXCEPTION( FP_GE(fraction, 0.0f) and FP_LE(fraction, 1.0f), "math error: Interpolate()" );

    Quaternion q;
    q.slerp( fraction, q0, q1 );
    return q;
}

/*****************************************************************************
 * Interpolate between two quaternions and positions.
 * fraction = 0 : return m0
 * fraction = 1 : return m1
 *****************************************************************************/
QuaternionPosition
Interpolate( const QuaternionPosition& qp0, const QuaternionPosition& qp1, const fp fraction )
{
    // Elegant.
    return QuaternionPosition( Interpolate( qp0.mQuat, qp1.mQuat, fraction ),
                               Interpolate( qp0.mPos , qp1.mPos , fraction ) );
}

/*****************************************************************************
 * Quaternion stream functions.
 *****************************************************************************/
std::istream& operator>>( std::istream& strm, Quaternion& quat )
{
    strm >> quat[0]
         >> quat[1]
         >> quat[2]
         >> quat[3];
    return strm;
}

std::ostream& operator<<( std::ostream& strm, const Quaternion& quat )
{
    // No pretty-formating as operator<<() has to reverse this.
    strm << quat[0] << ' '
         << quat[1] << ' '
         << quat[2] << ' '
         << quat[3] << ' ';  // no std::endl
    return strm;
}

} // namespace math
